#include "ScrollBar.h"


RScrollBar::RScrollBar()
{
    FillColor=SColor::FromHexRGB(0x6C6C6C);
    BorderColor=SColor(0,0,0,1);
    BorderSize=1;
    Width=20.f;
    Height=200.f;

    float EndButtonHeight=20.f;
    //create upper button
    RRectangleWidgetPtr UpperButton=NewWidget<RRectangleWidget>(this);
    {
        UpperButton->Width=20;
        UpperButton->Height=EndButtonHeight;
        UpperButton->FillColor= SColor::FromHexRGB(0x2AB900);
        UpperButton->BorderColor=SColor(0,0,0,1);
        UpperButton->BorderSize=1;     

        UpperButton->Anchor.TopReference=this;
        UpperButton->Anchor.LeftReference=this;
        UpperButton->Anchor.RightReference=this;

        auto Mouse=NewWidget<RMouseWidget>(UpperButton.Get());
        Mouse->Anchor.Fill(UpperButton);

        Mouse->OnClicked.Bind(RScrollBarWeakPtr(this),&RScrollBar::OnTopButtonClicked);

    }


    //create Bottom button
    auto BottomButton=NewWidget<RRectangleWidget>(this);
    {
        BottomButton->Width=20;
        BottomButton->Height=EndButtonHeight;
        BottomButton->FillColor= SColor::FromHexRGB(0x2AB900);
        BottomButton->BorderColor=SColor(0,0,0,1);
        BottomButton->BorderSize=1;     

        BottomButton->Anchor.BottomReference=this;
        BottomButton->Anchor.LeftReference=this;
        BottomButton->Anchor.RightReference=this;


        auto Mouse=NewWidget<RMouseWidget>(BottomButton.Get());
        Mouse->Anchor.Fill(BottomButton);

        Mouse->OnClicked.Bind(RScrollBarWeakPtr(this),&RScrollBar::OnBottomButtonClicked);

    }

    //create drag button
    {
        SlideArea=NewWidget<RRectangleWidget>(this);
        SlideArea->Name=CString(U"SliderArea");
        SlideArea->FillColor=SColor(0,0,0,0); //transparant
        SlideArea->Anchor.RightReference=this;
        SlideArea->Anchor.LeftReference=this;
        SlideArea->Anchor.TopReference=UpperButton;
        SlideArea->Anchor.TopReferenceEdge=EVerticalWidgetEdge::Bottom;
        SlideArea->Anchor.BottomReference=BottomButton;
        SlideArea->Anchor.BottomReferenceEdge=EVerticalWidgetEdge::Top;
        
        SlideAreaMouse=NewWidget<RMouseWidget>(SlideArea);
        SlideAreaMouse->Name=CString(U"SlideAreaMouse");
        SlideAreaMouse->Anchor.Fill(SlideArea); 
        SlideAreaMouse->OnClicked.Bind(this,&RScrollBar::OnBlankAreaClick);

        Slider=NewWidget<RRectangleWidget>(SlideArea);
        Slider->Width=20;
        //UpdateSliderSize();
        Slider->X=.0f;
        auto WeakSlider=Slider;
        Slider->Height=[this,WeakSlider]()->float{
            return SlideWindowLength/ContentTotalLength * SlideArea->PresentSize.Y;
        };
        Slider->Y= [this,WeakSlider]()->float{
            float SiderHeight = WeakSlider->Height.Get();
            return Percent*(SlideArea->PresentSize.Y -SiderHeight) ;
        };

        Slider->FillColor= SColor::FromHexRGB(0x2AB900);
        Slider->BorderColor=SColor(0,0,0,1);
        Slider->BorderSize=1;     

        Slider->Anchor.LeftReference=SlideArea;
        Slider->Anchor.RightReference=SlideArea;

        auto Mouse=NewWidget<RMouseWidget>(Slider.Get());
        Mouse->Anchor.Fill(Slider); 
        Mouse->Drag->bIsEnabled=true;
        Mouse->Drag->Target=(Slider);
        Mouse->Drag->Direction=EDragDirection::Vertical;

        Mouse->Drag->TargetWidgetMinY=0;
        Mouse->Drag->TargetWidgetMaxY=  TDelegate<float>::Create(
            [this]()->float{ 
                  return SlideArea->PresentSize.Y-Slider->PresentSize.Y;
        });   

        Mouse->Drag->OnDragMoved.Bind(RScrollBarWeakPtr(this),&RScrollBar::OnDragging);
         
    }

}

bool RScrollBar::OnTopButtonClicked(const SMouseButtonEvent&)
{
    if(Percent==0)
    {
        return false;
    }

    SetCurrentPercent(CMathBase::Max(0.f,Percent-0.1f));
    return true;

}
bool RScrollBar::OnBottomButtonClicked(const SMouseButtonEvent&)
{
    if(Percent==1)
    {
        return false;
    }

    SetCurrentPercent(CMathBase::Min(1.0f,Percent+0.1f));
    return true;
}

void RScrollBar::OnDragging(const SVec2& TotalMouseDistance)
{
    //calculate new percent

    auto NewPercent=Slider->Y.Get() /(SlideArea->PresentSize.Y -Slider->PresentSize.Y);
    Percent=NewPercent;
    OnPercentChanged.ExecuteIfBound(Percent);
}


void RScrollBar::SetContentTotalLength(float InLength,bool RecalculatePercent)
{
    float OldContentTotalLength=ContentTotalLength;

    ContentTotalLength=InLength;
    Visible=ShouldBeVisible();

    if(RecalculatePercent 
    && OldContentTotalLength!=ContentTotalLength 
    && ContentTotalLength>SlideWindowLength
    && OldContentTotalLength>SlideWindowLength
    )
    {
        float NewPercent=
            Percent*(OldContentTotalLength-SlideWindowLength) /(ContentTotalLength-SlideWindowLength);
        SetCurrentPercent(NewPercent);
    }
}

void RScrollBar::SetSlideWindowLength(float InLength)
{
    SlideWindowLength=InLength;
    Visible=ShouldBeVisible();

    // if(Visible.Get())
    // {
    //     UpdateSliderSize();
    // }
}

void RScrollBar::SetCurrentPercent(float InNewPosition)
{
    Percent=CMathBase::Clamp(InNewPosition,0.f,1.f);
    OnPercentChanged.ExecuteIfBound(Percent);

}


bool RScrollBar::OnBlankAreaClick(const SMouseButtonEvent&)
{
    auto NewSliderPosition=CMathBase::Clamp(SlideAreaMouse->GetMousePositionInContent().Y- Slider->PresentSize.Y/2,0,SlideArea->PresentSize.Y -Slider->PresentSize.Y);  
    auto NewPercent=NewSliderPosition /(SlideArea->PresentSize.Y -Slider->PresentSize.Y);
    SetCurrentPercent(NewPercent);

    return true;

}